/*
 * index.js
 */

/****************************************************
 JQUERY UI INTERNATIONALIZATION i18n
 ****************************************************/

/* Inicialización en español para la extensión 'UI date picker' para jQuery. */
/* Traducido por Vester (xvester@gmail.com). */
jQuery(function($) {
    $.datepicker.regional['es'] = {
        closeText: 'Cerrar',
        prevText: '&#x3C;Ant',
        nextText: 'Sig&#x3E;',
        currentText: 'Hoy',
        monthNames: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
            'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
        monthNamesShort: ['ene', 'feb', 'mar', 'abr', 'may', 'jun',
            'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
        dayNames: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
        dayNamesShort: ['dom', 'lun', 'mar', 'mié', 'juv', 'vie', 'sáb'],
        dayNamesMin: ['D', 'L', 'M', 'W', 'J', 'V', 'S'],
        weekHeader: 'Sm',
        dateFormat: 'mm/dd/yy',
        firstDay: 1,
        isRTL: false,
        showMonthAfterYear: false,
        yearSuffix: ''};
    $.datepicker.setDefaults($.datepicker.regional['es']);
});

/* Spanish initialisation for the jQuery time picker plugin. */
/* Writen by Jandro González (agonzalezalves@gmail.com) */
jQuery(function($) {
    $.timepicker.regional['es'] = {
        hourText: 'Hora',
        minuteText: 'Minuto',
        amPmText: ['AM', 'PM'],
        closeButtonText: 'Aceptar',
        nowButtonText: 'Ahora',
        deselectButtonText: 'Deseleccionar'};
    $.timepicker.setDefaults($.timepicker.regional['es']);
});

/****************************************************
 HERE MAPS CONFIGURATION AND GLOBAL VARIABLES
 ****************************************************/

nokia.Settings.set("appId", "dzmgTVK7no7eYGaa5mMf");
nokia.Settings.set("authenticationToken", "e9lEOKJl0dlVQKHnaNt2-A");
// Get the DOM node to which we will append the map
var $mapcontainer = $("#map");

nokia.Settings.set("defaultLanguage", "es-ES");

//Burbuja Información
var infoBubbles = new nokia.maps.map.component.InfoBubbles();
// Create a map inside the map container DOM node
var map = new nokia.maps.map.Display($mapcontainer.get(0), {
    baseMapType: nokia.maps.map.Display.SMARTMAP,
    components: [
        // Behavior collection
        infoBubbles,
        new nokia.maps.map.component.Behavior(),
        new nokia.maps.map.component.ZoomBar(),
        new nokia.maps.map.component.TypeSelector(),
        new nokia.maps.map.component.ScaleBar()],
    zoomLevel: 12,
    center: [6.202391, -75.576894]
});

var markersContainer = {buses: new nokia.maps.map.Container(), rutas: new nokia.maps.map.Container(), paradas: new nokia.maps.map.Container()};
var popups_opened = 0;
var routes_to_paint = 0;
var routes_managed = 0;
var routes_failed = 0;

/* We would like to add event listener on mouse click or finger tap so we check
 * nokia.maps.dom.Page.browser.touch which indicates whether the used browser has a touch interface.
 */
var TOUCH = nokia.maps.dom.Page.browser.touch,
        CLICK = TOUCH ? "tap" : "click";

/****************************************************
 ROUTES CALCULATION LISTENERS
 ****************************************************/
var icon_parada = new nokia.maps.gfx.BitmapImage("img/parada_3.png", null, 30, 30, 0, 0);

var onRouteCalculated = function(observedRouter, key, value) {
    if (value == "finished") {
        var routes = observedRouter.getRoutes(),
                route = routes[0],
                waypoints = route.waypoints,
                i, length = waypoints.length;

        var routesColors = {haciaeia: ["#FAEC21", "#FBF158", "#FDF690", "#FEFAC7"], desdeeia: ["#285999", "#1E4373", "#142C4C", "#0A1626"]};
        var arrowsColors = {haciaeia: "#000000", desdeeia: "#FFFFFF"};

        var direction = "desdeeia";

        $("#recorridos_activos .ruta_details[data-id_ruta='" + observedRouter.get("id_ruta") + "']").each(function() {
            if ($(".destino_details", this).data("id_parada") == window.app.id_parada_eia_palmas) {
                direction = "haciaeia";
            }
        });

        var lineColor = routesColors[direction][routes_managed % routesColors[direction].length];
        var linea_ruta = new nokia.maps.map.Polyline(route.shape, {
            pen: new nokia.maps.util.Pen({
                lineWidth: 5,
                strokeColor: lineColor
            }),
            arrows: new nokia.maps.util.Arrows({
                color: arrowsColors[direction]
            })
        });
        linea_ruta.set("id_ruta", observedRouter.get("id_ruta"));
        linea_ruta.addListener("mouseover", function(evt) {
            evt.target.set("pen", new nokia.maps.util.Pen({
                lineWidth: 5,
                strokeColor: "#F54046"
            }));
            evt.target.set("zIndex", 100);
            map.update(-1, 0);
        });

        linea_ruta.addListener("mouseout", function(evt) {
            evt.target.set("pen", new nokia.maps.util.Pen({
                lineWidth: 5,
                strokeColor: lineColor
            }));
            evt.target.set("zIndex", 2);
            map.update(-1, 0);
        });

        map.objects.remove(markersContainer.rutas);
        markersContainer.rutas.objects.add(linea_ruta);
        map.objects.add(markersContainer.rutas);

        var waypoints_ayuda_positions = observedRouter.get("waypoints_ayuda_positions");
        var paradas_waypoints = observedRouter.get("paradas_waypoints");
        map.objects.remove(markersContainer.paradas);
        for (i = 0; i < length; i++) {
            if (waypoints_ayuda_positions.indexOf(i) != -1) {
                continue;
            }

            var markerParada = new nokia.maps.map.Marker(waypoints[i].originalPosition, {
                icon: icon_parada,
                anchor: new nokia.maps.util.Point(15, 15)
            });
            markerParada.parada = paradas_waypoints[i];

            markerParada.addListener(CLICK, function(evt) {
                $("#mapapopups_menu .content").html(crearInfoBubbleParada(evt.target.parada.id_parada));
                $("#mapapopups_menu .content .parada .ruta").on('click tap', function(event) {
                    $(".ruta", $(this).parent()).removeClass('active');
                    $(".horario", $(this).parent()).removeClass('active');
                    $(".horario", $(this).parent()).hide();
                    $(".submit", $(this).parent()).hide();
                    $(this).addClass('active');
                    $(".title_horarios", $(this).parent()).show();
                    $(".horarios", $(this).parent()).show();
                    $(".horario[data-id_ruta='" + $(this).data('id_ruta') + "']", $(this).parent()).show();
                });
                $("#mapapopups_menu .content .parada .horario[data-bv='1']").on('click tap', function(event) {
                    $(".horario", $(this).parent()).removeClass('active');
                    $(this).addClass('active');
                    $(".submit", $(this).parent().parent()).show();
                });
                $("#mapapopups_menu .content .parada .horario[data-bv='0']").on('click tap', function(event) {
                    $(".horario", $(this).parent()).removeClass('active');
                    $(".submit", $(this).parent().parent()).hide();
                });
                $("#mapapopups_menu .content .parada .submit input[type=button]").on('click tap', function(event) {
                    $.ajax({
                        beforeSend: function(XMLHttpRequest) {
                            beforeSendReservaFromParada();
                        },
                        complete: function(XMLHttpRequest, textStatus) {
                            completeSendReservaFromParada();
                        },
                        data: {
                            'data[Reserva][parada]': $("#mapapopups_menu .content .parada").data('id_parada'),
                            'data[Reserva][ruta]': $("#mapapopups_menu .content .parada .ruta.active").data('id_ruta'),
                            'data[Reserva][horario]': $("#mapapopups_menu .content .parada .horario.active").data('id_horario'),
                            'data[Reserva][calendario]': $("#mapapopups_menu .content .parada .horario.active").data('calendario'),
                            'data[Reserva][terminos]': $("#mapapopups_menu .content .parada #terminos")[0].checked ? $("#mapapopups_menu .content .parada #terminos").val() : 0
                        },
                        dataType: "json",
                        error: function(XMLHttpRequest, textStatus, errorThrown) {
                            errorSendReservaFromParada(XMLHttpRequest, textStatus, errorThrown);
                        },
                        success: function(data, textStatus) {
                            successSendReservaFromParada(data, textStatus);
                        },
                        type: "post",
                        url: window.app.reservas_ajax_url
                    });
                });
                closeAllMenus();
                $("#mapapopups_menu").show();
            });

            markersContainer.paradas.objects.add(markerParada);
        }
        map.objects.add(markersContainer.paradas);
        routes_managed++;
        if (routes_to_paint == routes_managed) {
            if (haciaeia_filter) {
                $("#haciaeia_filter").trigger('haciaeia_filter');
            }
            else if (desdeeia_filter) {
                $("#desdeeia_filter").trigger('desdeeia_filter');
            }
            $("#refresh_modal").fadeOut(2000);
            if (routes_failed) {
                alert("Hay rutas que no se pudieron mostrar. Revise su conexión a internet y actualice la página para ver todas las rutas.");
            }
        }
    } else if (value == "failed") {
        console.log("The routing request failed");
        routes_failed++;
        routes_managed++;
        if (routes_to_paint == routes_managed) {
            if (haciaeia_filter) {
                $("#haciaeia_filter").trigger('haciaeia_filter');
            }
            else if (desdeeia_filter) {
                $("#desdeeia_filter").trigger('desdeeia_filter');
            }
            $("#refresh_modal").fadeOut(2000);
            if (routes_failed) {
                alert("Hay rutas que no se pudieron mostrar. Revise su conexión a internet y actualice la página para ver todas las rutas.");
            }
        }
    }
};

var calculateTimes = function(observedRouter, key, value) {
    if (value == "finished") {
        var routes = observedRouter.getRoutes(),
                route = routes[0],
                waypoints = route.waypoints;

        $("#buses .recorrido_details[data-id_recorrido='" + observedRouter.get("id_recorrido") + "']").each(function() {
            if (observedRouter.get("parada") == "proxima") {
                $(this).data("t_prox_parada", Math.ceil(route.summary.baseTime / 60));
                var $img = $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + observedRouter.get("id_recorrido") + "] .t_prox_parada img");
                $img.after(Math.ceil(route.summary.baseTime / 60) + " min*");
                $img.remove();
            }
            else if (observedRouter.get("parada") == "destino") {
                $(this).data("t_destino", Math.ceil(route.summary.baseTime / 60));
                var $img = $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + observedRouter.get("id_recorrido") + "] .t_destino img");
                $img.after(Math.ceil(route.summary.baseTime / 60) + " min*");
                $img.remove();
            }
        });

    } else if (value == "failed") {
        console.log("The routing request failed");
    }
};

/****************************************************
 PLOT MAP ELEMENTS
 ****************************************************/

function graficarRutaParadas(id_ruta, paradas, waypoints_ayuda) {
    var paradas_length = paradas.length;
    var waypoints_ayuda_length = waypoints_ayuda.length;

    paradas = sortObjects(paradas, "orden_ruta", true);
    waypoints_ayuda = sortObjects(waypoints_ayuda, "id_waypoint_parada", true);

    var paradas_waypoints = [];
    var waypoints_ayuda_positions = [];
    for (j in waypoints_ayuda) {
        paradas_waypoints[waypoints_ayuda[j].id_waypoint_parada - 1] = waypoints_ayuda[j];
        waypoints_ayuda_positions.push(waypoints_ayuda[j].id_waypoint_parada - 1);
    }

    var i = 0;
    for (j in paradas) {
        while (paradas_waypoints[i] !== undefined) {
            i++;
        }
        paradas_waypoints[i++] = paradas[j];
    }

    var waypoints = new nokia.maps.routing.WaypointParameterList();
    for (var i = 0; i <= paradas_length + waypoints_ayuda_length - 1; i++) {
        waypoints.addCoordinate(new nokia.maps.geo.Coordinate(Number(paradas_waypoints[i].latitud), Number(paradas_waypoints[i].longitud)));
    }

    router = new nokia.maps.routing.Manager();
    router.set("id_ruta", id_ruta);
    router.set("waypoints_ayuda_positions", waypoints_ayuda_positions);
    router.set("paradas_waypoints", paradas_waypoints);
    router.addObserver("state", onRouteCalculated);
    var mode = {
        type: "shortest",
        transportModes: ["car"],
        trafficMode: "disabled",
        options: ""
    };
    router.calculateRoute(waypoints, mode);
}

var icon_desdeeia = new nokia.maps.gfx.BitmapImage("img/bus_desde_eia.png", null, 33, 22, 0, 0);
var icon_haciaeia = new nokia.maps.gfx.BitmapImage("img/bus_hacia_eia.png", null, 33, 22, 0, 0);
var followId = 0;

function graficarBus(id_recorrido, latitud, longitud, ruta, estado, estado_descripcion, fecha_actualizacion, hora_salida, hora_llegada, disponibilidad, prox_parada, latitud_prox_parada, longitud_prox_parada, id_destino, destino, latitud_destino, longitud_destino) {

    var standardMarker = new nokia.maps.map.Marker(
            new nokia.maps.geo.Coordinate(Number(latitud), Number(longitud)), {
        icon: id_destino == window.app.id_parada_eia_palmas ? icon_haciaeia : icon_desdeeia,
        anchor: new nokia.maps.util.Point(16, 11)
    });
    var circleMarker = new nokia.maps.map.Circle(new nokia.maps.geo.Coordinate(Number(latitud), Number(longitud)), 100, {brush: {color: "#6EC4FFAA"}, pen: {strokeColor: "#089AFF"}});

    standardMarker.addListener(CLICK, function(evt) {
        // infoBubbles.openBubble(crearInfoBubbleBus(id_recorrido, latitud, longitud, ruta, estado, estado_descripcion, hora_salida, hora_llegada, disponibilidad, prox_parada, latitud_prox_parada, longitud_prox_parada, destino, latitud_destino, longitud_destino),
        //      new nokia.maps.geo.Coordinate(Number(latitud), Number(longitud)),
        //      function () {
        //          popups_opened = 0;
        //          refresh = true;
        //          if (refreshUser) {
        //              refreshPress(refresh);
        //          }
        //      });
        // popups_opened = 1;
        // if (refresh) {
        //  refresh = false;
        //  if (refreshUser) {
        //      refreshPress(refresh);
        //  }
        // }
        $("#mapapopups_menu .content").html(crearInfoBubbleBus(id_recorrido, latitud, longitud, ruta, estado, estado_descripcion, fecha_actualizacion, hora_salida, hora_llegada, disponibilidad, prox_parada, latitud_prox_parada, longitud_prox_parada, destino, latitud_destino, longitud_destino));
        $("#mapapopups_menu .content .recorrido .follow").on('click tap', function(event) {
            event.preventDefault();
            if (followId != Number($(this).parents(".recorrido").data('id_recorrido'))) {
                $(this).addClass('active');
                $(this).attr('tooltip-content', 'No seguir');
                followId = Number($(this).parents(".recorrido").data('id_recorrido'));
                map.set("zoomLevel", 17);
                map.set("center", [latitud, longitud]);
            }
            else {
                $(this).removeClass('active');
                $(this).attr('tooltip-content', 'Seguir');
                followId = 0;
            }
        });
        closeAllMenus();
        $("#mapapopups_menu").show();
    });

    // Next we need to add it to the map's object collection so it will be rendered onto the map.
    var container = new nokia.maps.map.Container();
    container.objects.addAll([standardMarker, circleMarker]);
    map.objects.remove(markersContainer.buses);
    markersContainer.buses.objects.add(container);
    map.objects.add(markersContainer.buses);
}

/****************************************************
 INFOBUBBLES CONTENT CREATION
 ****************************************************/

function crearInfoBubbleBus(id_recorrido, latitud, longitud, ruta, estado, estado_descripcion, fecha_actualizacion, hora_salida, hora_llegada, disponibilidad, prox_parada, latitud_prox_parada, longitud_prox_parada, destino, latitud_destino, longitud_destino) {
    var router_prox_parada = new nokia.maps.routing.Manager();
    router_prox_parada.set("id_recorrido", id_recorrido);
    router_prox_parada.set("parada", "proxima");
    //router_prox_parada.addObserver("state", calculateTimes);
    var mode = {
        type: "shortest",
        transportModes: ["car"],
        trafficMode: "disabled",
        options: ""
    };
    var waypoints_prox_parada = new nokia.maps.routing.WaypointParameterList();

    waypoints_prox_parada.addCoordinate(new nokia.maps.geo.Coordinate(Number(latitud), Number(longitud)));
    waypoints_prox_parada.addCoordinate(new nokia.maps.geo.Coordinate(Number(latitud_prox_parada), Number(longitud_prox_parada)));

    //router_prox_parada.calculateRoute(waypoints_prox_parada, mode);

    var router_destino = new nokia.maps.routing.Manager();
    router_destino.set("id_recorrido", id_recorrido);
    router_destino.set("parada", "destino");
    //router_destino.addObserver("state", calculateTimes);

    var waypoints_destino = new nokia.maps.routing.WaypointParameterList();

    waypoints_destino.addCoordinate(new nokia.maps.geo.Coordinate(Number(latitud), Number(longitud)));
    waypoints_destino.addCoordinate(new nokia.maps.geo.Coordinate(Number(latitud_destino), Number(longitud_destino)));

    //router_destino.calculateRoute(waypoints_destino, mode);

    var following = "";
    var tooltip_content = "Seguir";
    if (id_recorrido == followId) {
        following = "active";
        tooltip_content = "No seguir";
    }

    var html = "";
    if (estado_descripcion != null) {
        html = '<div class="recorrido" data-id_recorrido="' + id_recorrido + '" >' +
                '<div class="ruta">Ruta: <span class="recorrido_text">' + ruta + '</span> <span class="tooltip follow ' + following + '" tooltip-content="' + tooltip_content + '"><span class="icon seguir"></span></span></div>' +
                '<div class="estado">Estado: <span class="recorrido_text">' + estado_descripcion + '</span></div>' +
                '<div class="horario">Horario: <span class="recorrido_text">' + hora_salida + ' - ' + hora_llegada + '</span></div>' +
                '<div class="disponibilidad">Disponibilidad: <span class="recorrido_text">' + disponibilidad + ' cupos</span></div>' +
                '<div class="fecha_actualizacion">Fecha Actualización: <span class="recorrido_text">' + fecha_actualizacion + '</span></div>' +
                '<div class="prox_parada">Próxima parada: <span class="recorrido_text">' + prox_parada + '</span></div>' +
                '<div class="t_prox_parada block"><span class="recorrido_text centered">' + '<img src="img/ajax-loader.gif" alt="Cargando tiempo..." />' + '</span></div>' +
                '<div class="title_destino">Destino</div><div class="destino"><span class="recorrido_text block"><span class="centered">' + destino + '</span> - <span class="t_destino centered">' + '<img src="img/ajax-loader.gif" alt="Cargando tiempo..." />' + '</span></span></div>' +
                '<div class="note">*Tiempos estimados sin tener en cuenta tráfico</div>';
    }
    else {
        html = '<div class="recorrido" data-id_recorrido="' + id_recorrido + '" >' +
                '<div class="ruta">Ruta: <span class="recorrido_text">' + ruta + '</span> <span class="tooltip follow ' + following + '" tooltip-content="' + tooltip_content + '"><span class="icon seguir"></span></span></div>' +
                '<div class="estado">Estado: <span class="recorrido_text">' + estado + '</span></div>' +
                '<div class="horario">Horario: <span class="recorrido_text">' + hora_salida + ' - ' + hora_llegada + '</span></div>' +
                '<div class="disponibilidad">Disponibilidad: <span class="recorrido_text">' + disponibilidad + ' cupos</span></div>' +
                '<div class="fecha_actualizacion">Fecha Actualización: <span class="recorrido_text">' + fecha_actualizacion + '</span></div>' +
                '<div class="prox_parada">Próxima parada: <span class="recorrido_text">' + prox_parada + '</span></div>' +
                '<div class="t_prox_parada block"><span class="recorrido_text centered">' + '<img src="img/ajax-loader.gif" alt="Cargando tiempo..." />' + '</span></div>' +
                '<div class="title_destino">Destino</div><div class="destino"><span class="recorrido_text block"><span class="centered">' + destino + '</span> - <span class="t_destino centered">' + '<img src="img/ajax-loader.gif" alt="Cargando tiempo..." />' + '</span></span></div>' +
                '<div class="note">*Tiempos estimados sin tener en cuenta tráfico</div>';
    }

    if (estado == "movimiento") {
        html += '<div class="bus_estado"><span class="icon bus-verde"></span></div>';
    }
    else if (estado == "detenido") {
        html += '<div class="bus_estado"><span class="icon bus-naranja"></span></div>';
    }
    else {
        html += '<div class="bus_estado"><span class="icon bus-rojo"></span></div>';
    }

    html += '</div>';

    return html;
}

function crearInfoBubbleParada(id_parada) {
    var paradas = $("#recorridos_activos [data-id_parada='" + id_parada + "']");
    var rutas = paradas.parent();
    var nombre_parada = $("#recorridos_activos [data-id_parada='" + id_parada + "']").data('nombre_parada');

    var html = '<div class="parada" data-id_parada="' + id_parada + '" >' +
            '<div class="nombre_parada">Parada: <span class="parada_text">' + nombre_parada + '</span></div>' +
            '<div class="title_rutas">Rutas</div>';

    var horarios = '';
    for (var n = 0; n < rutas.length; n++) {
        if ($('#recorridos_activos .ruta_details[data-id_ruta="' + $(rutas[n]).data("id_ruta") + '"] .destino_details').data('id_parada') == id_parada) {
            continue;
        }
        html += '<div class="ruta" data-id_ruta="' + $(rutas[n]).data("id_ruta") + '"><span class="parada_text">' + $(rutas[n]).data("nombre_ruta") + '</span></div>';
        var posibles_horarios = {};
        $(".horario_details", $(rutas[n]).parent()).each(function(index, el) {
            var dates = $(this).data("dias_aplica").split("-");
            var hour_minutes_seg = $(this).data("hora_salida").split(":");
            for (i in dates) {
                var day = decode_dias(dates[i]);
                if (posibles_horarios[day] == undefined) {
                    posibles_horarios[day] = [];
                }
                posibles_horarios[day].push({hour: hour_minutes_seg[0], minutes: hour_minutes_seg[1], id_horario: $(this).data('id_horario')});
            }
        });
        var today_date = new Date();
        var j = 0;
        var day = today_date.getDay();
        while (j < 2 && day - today_date.getDay() <= Number(window.app.reservas_max_days_limit)) {
            if (posibles_horarios[day % 7] == undefined) {
                day++;
                continue;
            }
            for (i in posibles_horarios[day % 7]) {
                var bookingValid = true;
                if (j >= 2) {
                    break;
                }
                if (day < 7 && today_date.getDay() == day % 7) {
                    if (today_date.getHours() >= posibles_horarios[day % 7][i].hour && today_date.getMinutes() > posibles_horarios[day % 7][i].minutes) {
                        continue;
                    }
                    else if (today_date.getHours() + Number(window.app.reservas_min_hours_limit) > posibles_horarios[day % 7][i].hour) {
                        bookingValid = false;
                    }
                    else if (today_date.getHours() + Number(window.app.reservas_min_hours_limit) == posibles_horarios[day % 7][i].hour && today_date.getMinutes() > posibles_horarios[day % 7][i].minutes) {
                        bookingValid = false;
                    }
                }
                var datetime = new Date(today_date.getFullYear(), today_date.getMonth(), today_date.getDate() + day - today_date.getDay(), posibles_horarios[day % 7][i].hour, posibles_horarios[day % 7][i].minutes);
                var timestring = '';
                if (posibles_horarios[day % 7][i].hour > 12) {
                    timestring += (posibles_horarios[day % 7][i].hour % 12) + ":" + posibles_horarios[day % 7][i].minutes + " pm";
                }
                else if (posibles_horarios[day % 7][i].hour == 0) {
                    timestring += "12:" + posibles_horarios[day % 7][i].minutes + " am";
                }
                else {
                    timestring += posibles_horarios[day % 7][i].hour + ":" + posibles_horarios[day % 7][i].minutes + " am";
                }
                var adate = datetime.toDateString().split(" ");
                var datestring = '';
                datestring += translate_weekday(adate[0]) + ', ';
                datestring += translate_month(adate[1]) + ' ';
                datestring += adate[2] + ', ';
                datestring += adate[3];
                var time_remainingstring = '';
                var date_diff = datetime - today_date;
                var one_day = 1000 * 60 * 60 * 24;
                var days = 0;
                if (days = Math.floor(date_diff / one_day)) {
                    if (days == 1) {
                        time_remainingstring += days + " d&iacute;a";
                    }
                    else {
                        time_remainingstring += days + " d&iacute;as";
                    }
                }
                var hours = 0;
                if (hours = Math.floor((date_diff - (days * one_day)) / (one_day / 24))) {
                    if (days) {
                        time_remainingstring += ", ";
                    }
                    if (hours == 1) {
                        time_remainingstring += hours + " hora";
                    }
                    else {
                        time_remainingstring += hours + " horas";
                    }
                }
                var mins = 0;
                if (mins = Math.floor((date_diff - (days * one_day) - (hours * (one_day / 24))) / (one_day / (24 * 60)))) {
                    if (days || hours) {
                        time_remainingstring += ", ";
                    }
                    if (mins == 1) {
                        time_remainingstring += mins + " minuto";
                    }
                    else {
                        time_remainingstring += mins + " minutos";
                    }

                }
                if (bookingValid) {
                    horarios += '<div class="horario" data-bv="1" data-id_ruta="' + $(rutas[n]).data("id_ruta") + '" data-id_horario="' + posibles_horarios[day % 7][i].id_horario + '" data-calendario="' + (datetime.getMonth() + 1) + '/' + datetime.getDate() + '/' + datetime.getFullYear() + '" >';
                }
                else {
                    horarios += '<div class="horario" data-bv="0" data-id_ruta="' + $(rutas[n]).data("id_ruta") + '" data-id_horario="' + posibles_horarios[day % 7][i].id_horario + '" data-calendario="' + (datetime.getMonth() + 1) + '/' + datetime.getDate() + '/' + datetime.getFullYear() + '" >';
                }
                if (j == 0) {
                    horarios += '<div class="subtitle_horario">Pr&oacute;xima Salida:</div>';
                }
                else {
                    horarios += '<div class="subtitle_horario">Siguiente Salida:</div>';
                }
                horarios += '<div class="hora_parada"><span class="icon reloj"></span><span class="parada_text">' + timestring + '</span></div>';
                horarios += '<div class="fecha_parada"><span class="parada_text">' + datestring + '</span></div>';
                horarios += '<div class="t_faltante"><span class="parada_text">' + time_remainingstring + '</span></div>';
                horarios += '</div>';
                j++;
            }
            if (j < 2) {
                day++;
            }
        }
        if (j == 0) {
            horarios += '<div data-id_ruta="' + $(rutas[n]).data("id_ruta") + '" >No hay horarios disponibles</div>';
        }
    }

    if (horarios != '') {
        horarios = '<div class="title_horarios">Horarios</div>' + '<div class="horarios">' + horarios + '</div>';
        html += horarios;
        html += '<div class="submit link">';
        html += '<div class="input checkbox required" style="text-align: center;">' +
                '<input type="checkbox" value="1" id="terminos">' +
                '<label for="ReservaTerminos">' +
                'Acepta ' + $('a.terminosLink')[0].outerHTML +
                '</label>' +
                '</div>';
        html += '<input type="button" id="btnReservaParada" value="Reservar">' +
                '</div>';
    }
    else {
        html += '<div>No hay rutas disponibles</div>';
    }

    html += '<div class="parada_img"><span class="icon pare"></span></div>';

    html += '</div>';

    return html;
}

/****************************************************
 BUSES AND RUTAS OPERATIONS
 ****************************************************/

function actualizarBuses() {
    $("#buses .recorrido_details").each(function() {
        graficarBus($(this).data("id_recorrido"), $(this).data("latitud"), $(this).data("longitud"), $(this).data("ruta"), $(this).data("estado"), $(this).data("estado_descripcion"), $(this).data("fecha_actualizacion"), $(this).data("hora_salida"), $(this).data("hora_estimada_llegada"), $(this).data("disponibilidad"), $(this).data("prox_parada"), $(this).data("latitud_prox_parada"), $(this).data("longitud_prox_parada"), $(this).data("id_destino"), $(this).data("destino"), $(this).data("latitud_destino"), $(this).data("longitud_destino"));
    });
}

function borrarBuses() {
    map.objects.remove(markersContainer.buses);
    markersContainer.buses = new nokia.maps.map.Container();
}

function actualizarRutas() {
    routes_failed = 0;
    routes_managed = 0;
    routes_to_paint = $("#recorridos_activos .ruta_details").length;
    $("#recorridos_activos .ruta_details").each(function() {
        var paradas = [];
        $(".origen_details", this).each(function() {
            paradas.push({id_parada: $(this).data("id_parada"), tipo_parada: $(this).data("tipo_parada"), latitud: $(this).data("latitud"), longitud: $(this).data("longitud"), orden_ruta: $(this).data("orden_ruta")});
        });
        $(".parada_details", this).each(function() {
            paradas.push({id_parada: $(this).data("id_parada"), tipo_parada: $(this).data("tipo_parada"), latitud: $(this).data("latitud"), longitud: $(this).data("longitud"), orden_ruta: $(this).data("orden_ruta")});
        });
        $(".destino_details", this).each(function() {
            paradas.push({id_parada: $(this).data("id_parada"), tipo_parada: $(this).data("tipo_parada"), latitud: $(this).data("latitud"), longitud: $(this).data("longitud"), orden_ruta: $(this).data("orden_ruta")});
        });
        var waypoints_ayuda = [];
        $(".waypoint_details", this).each(function() {
            waypoints_ayuda.push({id_waypoint_parada: $(this).data("id_waypoint_parada"), latitud: $(this).data("latitud"), longitud: $(this).data("longitud")});
        });
        graficarRutaParadas($(this).data("id_ruta"), paradas, waypoints_ayuda);
    });
}

function borrarRutas() {
    map.objects.remove(markersContainer.rutas);
    markersContainer.rutas = new nokia.maps.map.Container();
}

function borrarParadas() {
    map.objects.remove(markersContainer.paradas);
    markersContainer.paradas = new nokia.maps.map.Container();
}

/****************************************************
 DOCUMENT READY
 ****************************************************/

$(document).ready(function() {
    updatePlaneoMiViajeDataTablesData();
    createDateAndTimePickers();
    actualizarRutas();
    actualizarBuses();
});

var refresh = true;
var refreshUser = true;
$(window).bind("load", function() {
    $("#refresh_modal").hide();
    window.setInterval(refresh_timer, Number(window.app.refresh_time) * 1000);
    window.setInterval(prediction_timer, 500);
});

var refresh_timer = function() {
    if (popups_opened == 0 && refresh && refreshUser) {
        refreshMapInfo();
    }
}

var alertShowed = false;
function refreshMapInfo() {
    // $("#refresh_modal").fadeIn(1000);
    $.ajax({
        dataType: "json",
        url: app.r_a_url,
        success: function(data) {
            $("#alternative_content #page_data #buses").html(data.buses);
            $("#alternative_content #page_data #recorridos_activos").html(data.recorridos_activos);

            //<Predicciones>
            prediction_info_refresh(data);
            //</Predicciones>

            //borrarBuses();
            // borrarParadas();
            // borrarRutas();
            // actualizarRutas();

            //actualizarBuses();

            var infoBubbleBusEmpty = true;
            var $recorrido;
            if (followId) {
                $recorrido = $("#buses .recorrido_details[data-id_recorrido=" + followId + "]");
            }
            else if ($("#mapapopups_menu .content").html() != "" && $("#mapapopups_menu .content > .recorrido").length > 0) {
                infoBubbleBusEmpty = false;
                $recorrido = $("#buses .recorrido_details[data-id_recorrido=" + $("#mapapopups_menu .content > .recorrido").data('id_recorrido') + "]");
            }
            if ($recorrido && $recorrido.length && $recorrido.length > 0) {
                $("#mapapopups_menu .content").html(crearInfoBubbleBus($recorrido.data('id_recorrido'), $recorrido.data('latitud'), $recorrido.data('longitud'), $recorrido.data('ruta'), $recorrido.data('estado'), $recorrido.data('estado_descripcion'), $recorrido.data('fecha_actualizacion'), $recorrido.data('hora_salida'), $recorrido.data('hora_estimada_llegada'), $recorrido.data('disponibilidad'), $recorrido.data('prox_parada'), $recorrido.data('latitud_prox_parada'), $recorrido.data('longitud_prox_parada'), $recorrido.data('destino'), $recorrido.data('latitud_destino'), $recorrido.data('longitud_destino')));
                $("#mapapopups_menu .content .recorrido .follow").on('click tap', function(event) {
                    event.preventDefault();
                    if (followId != Number($(this).parents(".recorrido").data('id_recorrido'))) {
                        $(this).addClass('active');
                        $(this).attr('tooltip-content', 'No seguir');
                        followId = Number($(this).parents(".recorrido").data('id_recorrido'));
//                        map.set("zoomLevel", 17);
                        map.set("center", [$recorrido.data('latitud'), $recorrido.data('longitud')]);
                    }
                    else {
                        $(this).removeClass('active');
                        $(this).attr('tooltip-content', 'Seguir');
                        followId = 0;
                    }
                });
            } else {
                if (followId || (!infoBubbleBusEmpty && $("#mapapopups_menu").is(':visible'))) {
                    $("#mapapopups_menu").hide();
                    displayNotification('El bus con ruta ' + $("#mapapopups_menu .content .recorrido .ruta .recorrido_text").html() + ', con horario ' + $("#mapapopups_menu .content .recorrido .horario .recorrido_text").html() + ', ha finalizado.');
                    $("#mapapopups_menu .content").html('');
                }
                followId = 0;
            }
        },
        error: function(jqXHR, textStatus, errorThrown) {
            if (jqXHR.status != 403 && jqXHR.status != 401) {
                if (textStatus == "error" && errorThrown == "") {
                    if (!alertShowed) {
                        location.reload();
                        alertShowed = true;
                    }
                }
                else if (errorThrown != "") {
                    displayNotification("Ocurrio un error inesperado: " + textStatus + "(" + errorThrown + ")");
                }
            }
        },
        statusCode: {
            403: function() {
                if (!alertShowed) {
                    alert("Su sesión ha caducado. Será redireccionado al login.");
                    location.reload();
                    alertShowed = true;
                }
            },
            401: function() {
                if (!alertShowed) {
                    // alert("Su sesión ha caducado. Será redireccionado al login.");
                    location.reload();
                    alertShowed = true;
                }
            }
        }
    });
}

/****************************************************
 Predicciones
 ****************************************************/

var pred_estado = null;
var pred_datos = null;
var pred_iniciada = false;
var pred_hora_server = null;
var pred_hora_local = null;

function prediction_timer() {
    var tiempo_inicial = new Date();
    if (!pred_iniciada) {
        //Inicializar data para predicciones....
        pred_iniciada = true;

        //Usar ajax para solicitar datos basicos para predicciones...
        $.get(app.pred_data_url,
                function(data_predicciones) {
                    pred_estado = [];
                    var idx;

                    for (idx = 0; idx < data_predicciones.length; idx++) {
                        //Lista vacia (recorridos por ruta en posicion idx
                        pred_estado[idx] = [];
                    }

                    pred_datos = data_predicciones;

                    //Informacion adicional pre-calculada localmente...
                    //Solo se necesita una por ruta...
                    for (idx = 0; idx < data_predicciones.length; idx++) {
                        pred_datos[idx].porcentages_ruta = obtener_porcentajes_ruta(pred_datos[idx].coordenadas);
                        pred_datos[idx].paradas_posiciones = puntos_cercanos_coordenadas(pred_datos[idx].paradas, pred_datos[idx].coordenadas);
                    }
                });

        return;
    }

    if (pred_datos !== null) {
        var tiempo_actual = new Date();
        var delta_segundos;
        var k;
        var rec_idx;
        var sim_state;
        var velocidades_ruta;
        var prediccion;
        var pos_proxima_parada;
        var t_llegada;

        for (k = 0; k < pred_estado.length; k++) {
            velocidades_ruta = extraer_velocidades_ruta(pred_datos[k].coordenadas);

            for (rec_idx = 0; rec_idx < pred_estado[k].length; rec_idx++) {
                sim_state = pred_estado[k][rec_idx];
                if (sim_state != null) {
                    //Diferencia entre tiempo actual y ultima actualizacion del server
                    delta_segundos = (tiempo_actual.getTime() - sim_state.ultimo_tiempo_coordenada.getTime()) / 1000.0;
                    //Edad de la actualizacion recibida del server...
                    delta_segundos += sim_state.delta_tiempo_extra;


                    prediccion = predecir_posicion_ruta(pred_datos[k].coordenadas, sim_state.posicion_actual_ruta, sim_state.posicion_factor_extra,
                            velocidades_ruta, delta_segundos, sim_state.historial_posiciones);
                    //console.log(delta_segundos + " : " + sim_state.prediccion_posicion + " - " + sim_state.prediccion_factor_extra + ", " + prediccion.posicion + "- " + prediccion.factor);
                    if (sim_state.prediccion_posicion + sim_state.prediccion_factor_extra < prediccion.posicion + prediccion.factor) {
                        //re-colocar el bus si una esta en una posicion mas avanzada...
                        sim_state.prediccion_posicion = prediccion.posicion;
                        sim_state.prediccion_factor_extra = prediccion.factor;

                        sim_state.prediccion_latitud = prediccion.latitud;
                        sim_state.prediccion_longitud = prediccion.longitud;

                        //actualizarPosicionBus(prediccion.latitud, prediccion.longitud);
                    }

                    var $detalles = $("#buses .recorrido_details[data-id_recorrido=" + sim_state.id_recorrido + "]");
                    $detalles.data("latitud", sim_state.prediccion_latitud);
                    $detalles.data("longitud", sim_state.prediccion_longitud);

                    //...actualizar siguiente parada basado en posicion actual...
                    while (sim_state.parada_actual < pred_datos[k].paradas.length - 1 &&
                            pred_datos[k].paradas_posiciones[sim_state.parada_actual + 1].index +
                            pred_datos[k].paradas_posiciones[sim_state.parada_actual + 1].tfact <
                            sim_state.prediccion_posicion + sim_state.prediccion_factor_extra) {

                        sim_state.parada_actual++;
                        sim_state.parada_tiempo_siguiente = null;
                    }

                    //... estimar tiempo de llegada...
                    //..... A proxima parada ....
                    if (sim_state.parada_actual + 1 < pred_datos[k].paradas_posiciones.length) {
                        pos_proxima_parada = pred_datos[k].paradas_posiciones[sim_state.parada_actual + 1];
                        t_llegada = predecir_tiempo_posicion(pred_datos[k].coordenadas, sim_state.prediccion_posicion, sim_state.prediccion_factor_extra,
                                velocidades_ruta, sim_state.historial_posiciones,
                                pos_proxima_parada.index, pos_proxima_parada.tfact);
                        if (sim_state.parada_tiempo_siguiente == null || t_llegada < sim_state.parada_tiempo_siguiente) {
                            sim_state.parada_tiempo_siguiente = t_llegada;
                        }
                    } else {
                        sim_state.parada_tiempo_siguiente = 0.0;
                    }

                    //.... A destino ....
                    t_llegada = predecir_tiempo_posicion(pred_datos[k].coordenadas, sim_state.prediccion_posicion, sim_state.prediccion_factor_extra,
                            velocidades_ruta, sim_state.historial_posiciones,
                            pred_datos[k].coordenadas.length - 2, 0.99);
                    if (sim_state.destino_tiempo == null || t_llegada < sim_state.destino_tiempo) {
                        sim_state.destino_tiempo = t_llegada;
                    }

                    //Seguir al bus...
                    if (followId) {
                        if (sim_state.id_recorrido == followId) {
                            //Actualizar la vista, centrar el bus...
                            map.set("center", [sim_state.prediccion_latitud, sim_state.prediccion_longitud]);
                        }
                    }

                    //Actualizar mensaje de siguiente parada....
                    $("#buses .recorrido_details[data-id_recorrido='" + sim_state.id_recorrido + "']").each(function() {
                        //...proxima....
                        $(this).data("t_prox_parada", Math.ceil(sim_state.parada_tiempo_siguiente / 60));

                        if (sim_state.parada_actual + 1 < pred_datos[k].paradas.length) {
                            $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + sim_state.id_recorrido + "] .prox_parada .recorrido_text").html(pred_datos[k].paradas[sim_state.parada_actual + 1].nombre_parada);
                            $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + sim_state.id_recorrido + "] .t_prox_parada .recorrido_text").html(pred_tiempo_texto(sim_state.parada_tiempo_siguiente) + "*");
                        } else {
                            $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + sim_state.id_recorrido + "] .prox_parada .recorrido_text").html(pred_datos[k].paradas[pred_datos[k].paradas.length - 1].nombre_parada);
                            $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + sim_state.id_recorrido + "] .t_prox_parada .recorrido_text").html("0");
                        }

                        //Destino...
                        $(this).data("t_destino", Math.ceil(sim_state.destino_tiempo / 60));
                        $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + sim_state.id_recorrido + "] .destino .recorrido_text .centered").html(pred_datos[k].paradas[pred_datos[k].paradas.length - 1].nombre_parada);
                        $("#mapapopups_menu .content .recorrido[data-id_recorrido=" + sim_state.id_recorrido + "] .destino .recorrido_text .t_destino").html(pred_tiempo_texto(sim_state.destino_tiempo) + "*");

                    });

                }
            }
        }

        borrarBuses();
        actualizarBuses();
    }

    var tiempo_final = new Date();
    //console.log(tiempo_final.getTime() - tiempo_inicial.getTime());
    //console.log(tiempo_inicial.getTime());
}

function prediction_info_refresh(data) {
    //tiempo de ultima actualizacion...
    pred_hora_server = data.hora_actual;
    pred_hora_local = new Date();

    if (pred_datos !== null) {
        //Verificar recorridos que estan y antes no estaban...
        //Primero crear una lista de los existentes, y asumir que no estaran ....

        var pre_existentes = [];
        var idx, ruta_idx, rec_idx;


        for (ruta_idx = 0; ruta_idx < pred_estado.length; ruta_idx++) {
            for (rec_idx = 0; rec_idx < pred_estado[ruta_idx].length; rec_idx++) {
                pre_existentes[pre_existentes.length] = {
                    indice_ruta: ruta_idx,
                    indice_rec: rec_idx,
                    id_recorrido: pred_estado[ruta_idx][rec_idx].id_recorrido,
                    post_existente: false
                };
            }
        }

        $("#buses .recorrido_details").each(function() {
            var tempo_id_recorrido = parseInt($(this).data("id_recorrido"));
            var tempo_id_ruta = parseInt($(this).data("id_ruta"));
            var recorrido_found = false;
            var tempo_idx;
            var tempo_ruta_idx;
            var tempo_rec_idx;

            //Buscar entre pre-existentes...
            for (tempo_idx = 0; tempo_idx < pre_existentes.length; tempo_idx++) {
                if (pre_existentes[tempo_idx].id_recorrido == tempo_id_recorrido) {
                    //Existente...
                    recorrido_found = true;
                    tempo_ruta_idx = pre_existentes[tempo_idx].indice_ruta;
                    tempo_rec_idx = pre_existentes[tempo_idx].indice_rec;
                    pre_existentes[tempo_idx].post_existente = true;
                    break;
                }
            }

            if (!recorrido_found) {
                //Nuevo... preparar para predicciones...

                //Determinar ruta correspondiente...
                for (tempo_idx = 0; tempo_idx < pred_datos.length; tempo_idx++) {
                    if (tempo_id_ruta == parseInt(pred_datos[tempo_idx].id_ruta)) {
                        //Ruta encontrada...
                        tempo_ruta_idx = tempo_idx;
                        break;
                    }
                }

                //Crear...
                tempo_rec_idx = pred_estado[tempo_ruta_idx].length;
                pred_estado[tempo_ruta_idx][tempo_rec_idx] = crear_nueva_prediccion();
                pred_estado[tempo_ruta_idx][tempo_rec_idx].id_recorrido = tempo_id_recorrido;
            }

            //Actualizar datos de coordenada...
            prediccion_actualizar_coordenada(pred_estado[tempo_ruta_idx][tempo_rec_idx], this, pred_datos[tempo_ruta_idx].coordenadas, pred_datos[tempo_ruta_idx].porcentages_ruta, pred_hora_server);
            //graficarBus($(this).data("id_recorrido"), $(this).data("latitud"), $(this).data("longitud"), $(this).data("ruta"), $(this).data("estado"), $(this).data("estado_descripcion"), $(this).data("fecha_actualizacion"), $(this).data("hora_salida"), $(this).data("hora_estimada_llegada"), $(this).data("disponibilidad"), $(this).data("prox_parada"), $(this).data("latitud_prox_parada"), $(this).data("longitud_prox_parada"), $(this).data("id_destino"), $(this).data("destino"), $(this).data("latitud_destino"), $(this).data("longitud_destino"));
        });

        //Eliminar aquellos que no estan marcados como post-existentes...
        for (idx = 0; idx < pre_existentes.length; idx++) {
            if (!pre_existentes[idx].post_existente) {

                //Buscar y eliminar...
                //(Notar que al eliminar elementos, el original indice_rec guardado ya no es una referencia valida,
                // y esto obliga a hacer busquedas)
                ruta_idx = pre_existentes[idx].indice_ruta;
                for (rec_idx = 0; rec_idx < pred_estado[ruta_idx].length; rec_idx++) {
                    if (pred_estado[ruta_idx][rec_idx].id_recorrido == pre_existentes[idx].id_recorrido) {
                        //Encontrado, remover...
                        pred_estado[ruta_idx].splice(rec_idx, 1);
                        break;
                    }
                }
            }
        }

        //console.log(pre_existentes);
        //console.log(post_existentes);
    }
}

function prediccion_actualizar_coordenada(sim_state, data_source, coordenadas_ruta, porcentages_ruta, server_hora_solicitud) {
    coord_id = $(data_source).data("fecha_actualizacion");

    if (sim_state.last_coord_id != coord_id) {
        sim_state.last_coord_id = coord_id;

        var punto_cercano;
        var coord_valida = true;

        var server_hora_coordenada = $(data_source).data("fecha_actualizacion");
        var edad_coordenada = dateStringToSeconds(server_hora_solicitud) - dateStringToSeconds(server_hora_coordenada);

        new_server_coord = {
            latitud: $(data_source).data("latitud"),
            longitud: $(data_source).data("longitud"),
            fecha_hora_envio_servidor: server_hora_coordenada
        };

        if (sim_state.last_server_coord == null) {
            //No hay coordenada previa, usar el mas cercano absoluto....
            //Ademas, siempre es valida....
            punto_cercano = punto_cercano_ruta_abs(new_server_coord.latitud, new_server_coord.longitud, coordenadas_ruta);
        } else {
            //Hay coordenada previa, usar el mas cercano relativo a la ultima posicion....
            var ultimo_tiempo = dateStringToSeconds(sim_state.last_server_coord.fecha_hora_envio_servidor);
            var tiempo_actual = dateStringToSeconds(new_server_coord.fecha_hora_envio_servidor);

            var delta_tiempo = (tiempo_actual - ultimo_tiempo);

            punto_cercano = punto_cercano_ruta_rel(new_server_coord.latitud, new_server_coord.longitud, coordenadas_ruta,
                    sim_state.posicion_actual_ruta, sim_state.posicion_factor_extra, delta_tiempo);
            //Verificar si es valida
            // 1) primero por distancia de punto mas cercano ruta...
            if (punto_cercano.distancia > PARAMETRO_rechazo_dist &&
                    porcentages_ruta[punto_cercano.index] >= PARAMETRO_rechazo_min &&
                    porcentages_ruta[punto_cercano.index] <= PARAMETRO_rechazo_max) {
                coord_valida = false;
                //console.log("Rechanzando coordenada");
            }

            /*
             // 2) segundo, por tiempo, solo aceptar coordenadas mas recientes...
             if (new_server_coord.fecha_hora_envio_servidor <= sim_state.last_server_coord.fecha_hora_envio_servidor){
             coord_valida = false;
             }
             */
        }

        if (coord_valida) {
            //Reemplazar solo si es mas reciente...

            sim_state.historial_posiciones[sim_state.historial_posiciones.length] = {
                "fecha_hora_envio_servidor": new_server_coord.fecha_hora_envio_servidor,
                "index": punto_cercano.index,
                "factor": punto_cercano.tfact
            };

            //Actualizar posicion en ruta...
            sim_state.posicion_actual_ruta = punto_cercano.index;
            sim_state.posicion_factor_extra = punto_cercano.tfact;

            //Nueva ultima coordenada
            sim_state.last_server_coord = new_server_coord;

            sim_state.ultimo_tiempo_coordenada = new Date();
            //console.log("Coordenada aceptada " + sim_state.posicion_actual_ruta + ", " + sim_state.posicion_factor_extra);
        }
    }

}

/****************************************************
 EVENT LISTENERS
 ****************************************************/

/*----------------------------------------------
 ADMINISTRAR LINK
 ----------------------------------------------*/

var a_clicked = false;
$("#administrar").on("click tap", function(event) {
    if (!a_clicked) {
        a_clicked = true;
        $("a", this)[0].click();
    }
    else {
        a_clicked = false;
    }
});

$("#administrar a").on("click tap", function() {
    a_clicked = true;
});

/*----------------------------------------------
 CLOSING BUTTTON
 ----------------------------------------------*/

$(".cerrar-negro, [class*=cerrar]").on("click tap", function() {
    $(this).parent().hide();
});

$("div[id$=menu] [class*=cerrar]").on("click tap", function(event) {
    $("#" + $(this).parent().attr("id").replace("_menu", "")).toggleClass("active");
});

/*----------------------------------------------
 MI BUS ANDANDO MENU
 ----------------------------------------------*/

function resetHaciaeiaDesdeeiaFilters() {
    if (haciaeia_filter || desdeeia_filter) {
        noFilterHaciaeiaDesdeeia();
    }
    haciaeia_filter = false;
    desdeeia_filter = false;
    $("#desdeeia_filter").removeClass('active');
    $("#haciaeia_filter").removeClass('active');
}

var haciaeia_filter = false;
$("#haciaeia_filter").on("click tap", function() {
    resetCheckboxFilter();
    haciaeia_filter = !haciaeia_filter;
    if (haciaeia_filter && desdeeia_filter) {
        desdeeia_filter = false;
        $("#desdeeia_filter").trigger('desdeeia_filter');
        $("#desdeeia_filter").removeClass('active');
    }
    $(this).trigger('haciaeia_filter');
    $(this).toggleClass('active');
});

var desdeeia_filter = false;
$("#desdeeia_filter").on("click tap", function() {
    resetCheckboxFilter();
    desdeeia_filter = !desdeeia_filter;
    if (desdeeia_filter && haciaeia_filter) {
        haciaeia_filter = false;
        $("#haciaeia_filter").trigger('haciaeia_filter');
        $("#haciaeia_filter").removeClass('active');
    }
    $(this).trigger('desdeeia_filter');
    $(this).toggleClass('active');
});

function mostrarSoloHaciaeia() {
    var id_rutas_ocultar = [];
    var id_paradas_ocultar = [];
    $("#recorridos_activos .ruta_details .destino_details:not([data-id_parada=" + window.app.id_parada_eia_palmas + "])").each(function() {
        id_rutas_ocultar.push($(this).parent("#recorridos_activos .ruta_details").data("id_ruta"));
        $(this).parent().children(":not(.waypoint_details)").each(function(index, el) {
            id_paradas_ocultar.push($(this).data("id_parada"));
        });
    });
    map.objects.remove(markersContainer.rutas);
    for (var i = markersContainer.rutas.objects.getLength() - 1; i >= 0; i--) {
        if (id_rutas_ocultar.indexOf(markersContainer.rutas.objects.get(i).get("id_ruta")) != -1) {
            markersContainer.rutas.objects.get(i).visibility = false;
        }
    }

    map.objects.add(markersContainer.rutas);

    map.objects.remove(markersContainer.paradas);
    for (var i = markersContainer.paradas.objects.getLength() - 1; i >= 0; i--) {
        if (id_paradas_ocultar.indexOf(markersContainer.paradas.objects.get(i).parada.id_parada) != -1) {
            markersContainer.paradas.objects.get(i).visibility = false;
            id_paradas_ocultar.splice(id_paradas_ocultar.indexOf(markersContainer.paradas.objects.get(i).parada.id_parada), 1);
        }
    }

    map.objects.add(markersContainer.paradas);
}

function mostrarSoloDesdeeia() {
    var id_rutas_ocultar = [];
    var id_paradas_ocultar = [];
    $("#recorridos_activos .ruta_details .destino_details[data-id_parada=" + window.app.id_parada_eia_palmas + "]").each(function() {
        id_rutas_ocultar.push($(this).parent("#recorridos_activos .ruta_details").data("id_ruta"));
        $(this).parent().children(":not(.waypoint_details)").each(function(index, el) {
            id_paradas_ocultar.push($(this).data("id_parada"));
        });
    });
    map.objects.remove(markersContainer.rutas);
    for (var i = markersContainer.rutas.objects.getLength() - 1; i >= 0; i--) {
        if (id_rutas_ocultar.indexOf(markersContainer.rutas.objects.get(i).get("id_ruta")) != -1) {
            markersContainer.rutas.objects.get(i).visibility = false;
        }
    }

    map.objects.add(markersContainer.rutas);

    map.objects.remove(markersContainer.paradas);
    for (var i = markersContainer.paradas.objects.getLength() - 1; i >= 0; i--) {
        if (id_paradas_ocultar.indexOf(markersContainer.paradas.objects.get(i).parada.id_parada) != -1) {
            markersContainer.paradas.objects.get(i).visibility = false;
            id_paradas_ocultar.splice(id_paradas_ocultar.indexOf(markersContainer.paradas.objects.get(i).parada.id_parada), 1);
        }
    }

    map.objects.add(markersContainer.paradas);
}

function noFilterHaciaeiaDesdeeia() {
    map.objects.remove(markersContainer.rutas);
    for (var i = markersContainer.rutas.objects.getLength() - 1; i >= 0; i--) {
        markersContainer.rutas.objects.get(i).visibility = true;
    }

    map.objects.add(markersContainer.rutas);

    map.objects.remove(markersContainer.paradas);
    for (var i = markersContainer.paradas.objects.getLength() - 1; i >= 0; i--) {
        markersContainer.paradas.objects.get(i).visibility = true;
    }

    map.objects.add(markersContainer.paradas);
}

$("#haciaeia_filter").on("haciaeia_filter", function() {
    if (haciaeia_filter) {
        mostrarSoloHaciaeia();
    }
    else {
        noFilterHaciaeiaDesdeeia();
    }
});

$("#desdeeia_filter").on("desdeeia_filter", function() {
    if (desdeeia_filter) {
        mostrarSoloDesdeeia();
    }
    else {
        noFilterHaciaeiaDesdeeia();
    }
});

$("#planear_nuevo_viaje").on("click tap", function(event) {
    event.preventDefault();
    $("#planeomiviaje").click();
});

/*----------------------------------------------
 LOCALIZAME BUTTON
 ----------------------------------------------*/

$("#localizame").on("click tap", function(event) {
    $(this).trigger('localizame');
});

var positionMarker;
var accuracyCircle;
var icon_usted_esta_aqui = new nokia.maps.gfx.BitmapImage("img/usted_esta_aqui.png");
$("#localizame").on("localizame", function(event) {
    if (typeof positionMarker !== "undefined") {
        map.objects.remove(positionMarker);
        map.objects.remove(accuracyCircle);
    }
    if (nokia.maps.positioning.Manager) {
        var positioning = new nokia.maps.positioning.Manager();
        positioning.getCurrentPosition(
                function(position) {
                    var coords = position.coords;
                    accuracyCircle = new nokia.maps.map.Circle(coords, coords.accuracy, {brush: {color: "#6EC4FFAA"}, pen: {strokeColor: "#089AFF"}});
                    positionMarker = new nokia.maps.map.Marker(coords, {
                        icon: icon_usted_esta_aqui,
                        anchor: new nokia.maps.util.Point(17, 17)
                    });
                    var distancia = getDistanceFromLatLonInKm(parseFloat(position.coords.latitude), parseFloat(position.coords.longitude), parseFloat("6.2359"), parseFloat("-75.5751"));
                    if (distancia > parseFloat(100)) {
                        displayNotification("Estas muy alejado de Medellín");
                    }
                    map.objects.addAll([accuracyCircle, positionMarker]);

                },
                function(error) {
                    var errorMsg = "Location could not be determined: ";
                    if (error.code == 1)
                        errorMsg += "PERMISSION_DENIED";
                    else if (error.code == 2)
                        errorMsg += "POSITION_UNAVAILABLE";
                    else if (error.code == 3)
                        errorMsg += "TIMEOUT";
                    else
                        errorMsg += "UNKNOWN_ERROR";
                    displayNotification(errorMsg);
                }
        );
        map.set("zoomLevel", 12);
        map.set("center", [6.2359, -75.5751]);
    }
});

/*----------------------------------------------
 PLANEO MI VIAJE MENU
 ----------------------------------------------*/

var desdeeia = false;
var desdeparada = false;
$("#desdeeia").on('click tap', function() {
    desdeeia = true;
    desdeparada = false;
    $("div[data-step_number=1]").hide();
    $("#step_1").removeClass('active');
    $("#destino_paradas").show();
    $("#step_2").addClass('active');
});
$("#desdeparada").on('click tap', function() {
    desdeeia = false;
    desdeparada = true;
    $("div[data-step_number=1]").hide();
    $("#step_1").removeClass('active');
    $("#origen_paradas").show();
    $("#step_2").addClass('active');
});

$("#steps_content .volver").on("click tap", function(e) {
    e.preventDefault();
    var $step_content = $(this).parents(".step_content");
    $step_content.hide();
    $("#step_" + $step_content.data('step_number')).removeClass('active');
    if ($step_content.data('step_number') - 1 == 2) {
        if (desdeeia) {
            $("div#destino_paradas").show();
        }
        else {
            $("div#origen_paradas").show();
        }
    }
    else {
        $("div[data-step_number=" + ($step_content.data('step_number') - 1) + "]").show();
    }
    $("#step_" + ($step_content.data('step_number') - 1)).addClass('active');
});

$("#steps_content .siguiente").on("click tap", function(e) {
    if ($("#ReservaRuta").val() != "") {
        var $error_message = $("div.errormessage", $(this).parents(".step_content"));
        $error_message.html("");
        $error_message.hide();
        goToNextStep(this);
    }
    else {
        var $error_message = $("div.errormessage", $(this).parents(".step_content"));
        $error_message.html("Debe seleccionar alguna parada");
        $error_message.fadeIn(500);
    }
});

$("#steps_content .cancelar").on("click tap", function(e) {
    e.preventDefault();
    eraseErrorMessages("Reserva");
    resetPlaneoMiViaje();
    $("#planeomiviaje").click();
});

var goToNextStep = function(container) {
    var $step_content = $(container).parents(".step_content");
    $step_content.hide();
    $("#step_" + $step_content.data('step_number')).removeClass('active');
    $("div[data-step_number=" + ($step_content.data('step_number') + 1) + "]").show();
    $("#step_" + ($step_content.data('step_number') + 1)).addClass('active');
};

var validateRutaSelection = function(step) {
    return $("#ReservaRuta").val() != "";
};

var resetPlaneoMiViaje = function() {
    $("#steps_content .content form input[name^=data][readonly]:not([type=submit])").each(function(index, el) {
        $(this).val("");
    });
    $("#steps_content .content form input[name^=data][type=checkbox]").each(function(index, el) {
       this.checked = false;
    });
    $("#steps_content .content table tr.selected").each(function(index, el) {
        $(this).removeClass('selected');
    });
    $(".hora").timepicker("destroy");
    $(".hora").removeAttr("id");
    $(".fecha").datepicker("destroy");
    $(".fecha").removeAttr("id");
    createDateAndTimePickers();
    $("#steps_bar .step_icon").each(function(index, el) {
        $(this).removeClass('active');
    });
    $("#steps_content .step_content").each(function(index, el) {
        $(this).hide();
    });
    $("#step_1").addClass('active');
    $("#origen_viaje").show();
};

var createDataTable = function(selector) {
    var asInitVals = [];
    var oTable = $(selector).dataTable({
        "bPaginate": true,
        "sPaginationType": "full_numbers",
        "iDisplayLength": 5,
        "bLengthChange": false,
        "bFilter": true,
        "bSort": false,
        "bInfo": true,
        "bAutoWidth": true,
        "sDom": 't<"dt_pag_wrapper"ip>',
        "bRetrieve": true,
        "oLanguage": {
            "sProcessing": "Procesando...",
            "sLengthMenu": "Mostrar _MENU_ registros",
            "sZeroRecords": "No se encontraron resultados",
            "sEmptyTable": "Ning&uacute;n dato disponible en esta tabla",
            "sInfo": "Mostrando registros del _START_ al _END_ de un total de _TOTAL_ registros",
            "sInfoEmpty": "Mostrando registros del 0 al 0 de un total de 0 registros",
            "sInfoFiltered": "(filtrado de un total de _MAX_ registros)",
            "sInfoPostFix": "",
            "sSearch": "Buscar:",
            "sUrl": "",
            "sInfoThousands": ",",
            "sLoadingRecords": "Cargando...",
            "oPaginate": {
                "sFirst": "Primero",
                "sLast": "&Uacute;ltimo",
                "sNext": "Siguiente",
                "sPrevious": "Anterior"
            },
            "fnInfoCallback": null,
            "oAria": {
                "sSortAscending": ": Activar para ordernar la columna de manera ascendente",
                "sSortDescending": ": Activar para ordernar la columna de manera descendente"
            }
        }
    });

    $("tfoot input", selector).keyup({tableTarget: selector, dataTableObj: oTable}, function(eventObject) {
        /* Filter on the column (the index) of this element */
        eventObject.data.dataTableObj.fnFilter($(this).val(), $("tfoot input", eventObject.data.tableTarget).index(this));
    });

    $("tfoot input", selector).each(function(i) {
        this.className = "search_init";
        asInitVals[i] = this.value;
    });

    $("tfoot input", selector).focus(function() {
        if (this.className == "search_init")
        {
            this.className = "";
            this.value = "";
        }
    });

    $("tfoot input", selector).blur({tableTarget: selector}, function(eventObject) {
        if (this.value == "")
        {
            this.className = "search_init";
            this.value = asInitVals[$("tfoot input", eventObject.data.tableTarget).index(this)];
        }
    });

    oTable.$("tr").on("click tap", {dataTableObj: oTable}, function(eventObject) {
        if ($(this).hasClass('selected')) {
            $(this).removeClass('selected');
            $("#ReservaRuta").val("");
        }
        else {
            eventObject.data.dataTableObj.$('tr.selected').removeClass('selected');
            $(this).addClass('selected');
            $("#resumen_viaje form #ReservaOrigen").val($(this).data("origen-nombre_parada"));
            $("#resumen_viaje form #ReservaParada").val($(this).data("id_parada"));
            $("#resumen_viaje form #ReservaDestino").val($(this).data("destino-nombre_parada"));
            $("#resumen_viaje form #ReservaNombreRuta").val($(this).data("nombre_ruta"));
            $("#resumen_viaje form #ReservaRuta").val($(this).data("id_ruta"));
            var validTimes = [];
            var date_time = {};
            $(".horario_details", $("#recorridos_activos .ruta_details[data-id_ruta=" + $(this).data("id_ruta") + "]").parent()).each(function(index, el) {
                var dates = $(this).data("dias_aplica").split("-");
                var hour_minutes_seg = $(this).data("hora_salida").split(":");
                for (i in dates) {
                    var day = decode_dias(dates[i]);
                    if (date_time[day] == undefined) {
                        date_time[day] = [];
                    }
                    date_time[day].push({hour: hour_minutes_seg[0], minutes: hour_minutes_seg[1], id_horario: $(this).data('id_horario')});
                }
            });
            $(".fecha").datepicker("destroy");
            $(".fecha").removeAttr("id");
            var today = false;
            var today_time = new Date();
            var today_date = new Date();
            today_date.setMilliseconds(0);
            today_date.setSeconds(0);
            today_date.setMinutes(0);
            today_date.setHours(0);
            $(".fecha").datepicker({
                minDate: 0,
                maxDate: "+" + window.app.reservas_max_days_limit + "D",
                beforeShowDay: function(date) {
                    if (date_time[date.getDay()] == undefined) {
                        return [false, ""];
                    }
                    else if (today_date.getTime() == date.getTime()) {
                        var valid = false;
                        for (var i = date_time[date.getDay()].length - 1; i >= 0; i--) {
                            if (today_time.getHours() + Number(window.app.reservas_min_hours_limit) < date_time[date.getDay()][i].hour) {
                                valid = true;
                                break;
                            }
                            else if (today_time.getHours() + Number(window.app.reservas_min_hours_limit) == date_time[date.getDay()][i].hour && today_time.getMinutes() <= Number(date_time[date.getDay()][i].minutes)) {
                                valid = true;
                                break;
                            }
                        }
                        return [valid, ""];
                    }
                    else {
                        return [true, ""];
                    }
                },
                onSelect: function(dateText, instance) {
                    $("#resumen_viaje form #ReservaCalendario").val(dateText);
                    var selected_date = new Date(Date.parse(dateText));
                    var day = selected_date.getDay();
                    if (selected_date.getTime() == today_date.getTime()) {
                        today = true;
                    }
                    else {
                        today = false;
                    }
                    $(".hora").timepicker("destroy");
                    $(".hora").removeAttr("id");
                    $(".hora").timepicker({
                        altField: '#ReservaNombreHorario',
                        onHourShow: function(hour) {
                            for (var i = date_time[day].length - 1; i >= 0; i--) {
                                if (date_time[day][i].hour == hour) {
                                    if (today) {
                                        if (today_time.getHours() + Number(window.app.reservas_min_hours_limit) > hour) {
                                            return false;
                                        }
                                        else if (today_time.getHours() + Number(window.app.reservas_min_hours_limit) == hour && today_time.getMinutes() > Number(date_time[day][i].minutes)) {
                                            return false;
                                        }
                                    }
                                    return true;
                                }
                            }
                            return false;
                        },
                        onMinuteShow: function(hour, minute) {
                            for (var i = date_time[day].length - 1; i >= 0; i--) {
                                if (date_time[day][i].hour == hour && date_time[day][i].minutes == minute) {
                                    if (today) {
                                        if (today_time.getHours() + Number(window.app.reservas_min_hours_limit) > hour) {
                                            return false;
                                        }
                                        else if (today_time.getHours() + Number(window.app.reservas_min_hours_limit) == hour && today_time.getMinutes() > minute) {
                                            return false;
                                        }
                                    }
                                    return true;
                                }
                            }
                            return false;
                        },
                        onSelect: function(time, inst) {
                            var atime = time.split(":");
                            var valid = false;
                            for (var i = date_time[day].length - 1; i >= 0; i--) {
                                if (date_time[day][i].hour == atime[0] && date_time[day][i].minutes == atime[1]) {
                                    $("#ReservaHorario").val(date_time[day][i].id_horario);
                                    valid = true;
                                    break;
                                }
                            }
                            if (valid) {
                                goToNextStep(this);
                            }
                        }
                    });
                    goToNextStep(this);
                }
            });
        }
    });

    return oTable;
};

var updateDataTableData = function(table_selector, table_rows) {
    var oTable = $(table_selector).dataTable();
    oTable.fnClearTable();
    oTable.fnDestroy();
    for (var i in table_rows) {
        $("tbody", table_selector).append(table_rows[i]);
    }
    createDataTable(table_selector);
};

var updatePlaneoMiViajeDataTablesData = function() {
    var TRs_destino_paradas = [];
    var TRs_origen_paradas = [];
    $("#recorridos_activos .recorrido_details").each(function() {
        var id_ruta = $(".ruta_details", this).data("id_ruta");
        var nombre_ruta = $(".ruta_details", this).data("nombre_ruta");
        var $origen = $(".ruta_details .origen_details", this);
        var $destino = $(".ruta_details .destino_details", this);

        if ($(this).hasClass('desdeeia')) {
            $(".ruta_details .parada_details", this).each(function() {
                var TR_destino_paradas = "<tr ";
                TR_destino_paradas += 'data-id_ruta="' + id_ruta + '" ';
                TR_destino_paradas += 'data-nombre_ruta="' + nombre_ruta + '" ';
                TR_destino_paradas += 'data-id_parada="' + $(this).data("id_parada") + '" ';
                TR_destino_paradas += 'data-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR_destino_paradas += 'data-origen-nombre_parada="' + $origen.data("nombre_parada") + '" ';
                TR_destino_paradas += 'data-destino-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR_destino_paradas += '>';
                TR_destino_paradas += '<td>' + $(this).data("nombre_parada") + '</td>';
                TR_destino_paradas += '<td>' + nombre_ruta + '</td>';
                TR_destino_paradas += "</tr>";
                TRs_destino_paradas.push(TR_destino_paradas);
            });

            $(".ruta_details .destino_details", this).each(function() {
                var TR = "<tr ";
                TR += 'data-id_ruta="' + id_ruta + '" ';
                TR += 'data-nombre_ruta="' + nombre_ruta + '" ';
                TR += 'data-id_parada="' + $(this).data("id_parada") + '" ';
                TR += 'data-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR += 'data-origen-nombre_parada="' + $origen.data("nombre_parada") + '" ';
                TR += 'data-destino-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR += '>';
                TR += '<td>' + $(this).data("nombre_parada") + '</td>';
                TR += '<td>' + nombre_ruta + '</td>';
                TR += "</tr>";
                TRs_destino_paradas.push(TR);
            });
        }
        else {
            $(".ruta_details .origen_details", this).each(function() {
                var TR = "<tr ";
                TR += 'data-id_ruta="' + id_ruta + '" ';
                TR += 'data-nombre_ruta="' + nombre_ruta + '" ';
                TR += 'data-id_parada="' + $(this).data("id_parada") + '" ';
                TR += 'data-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR += 'data-origen-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR += 'data-destino-nombre_parada="' + $destino.data("nombre_parada") + '" ';
                TR += '>';
                TR += '<td>' + $(this).data("nombre_parada") + '</td>';
                TR += '<td>' + nombre_ruta + '</td>';
                TR += "</tr>";
                TRs_origen_paradas.push(TR);
            });

            $(".ruta_details .parada_details", this).each(function() {
                var TR_origen_paradas = "<tr ";
                TR_origen_paradas += 'data-id_ruta="' + id_ruta + '" ';
                TR_origen_paradas += 'data-nombre_ruta="' + nombre_ruta + '" ';
                TR_origen_paradas += 'data-id_parada="' + $(this).data("id_parada") + '" ';
                TR_origen_paradas += 'data-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR_origen_paradas += 'data-origen-nombre_parada="' + $(this).data("nombre_parada") + '" ';
                TR_origen_paradas += 'data-destino-nombre_parada="' + $destino.data("nombre_parada") + '" ';
                TR_origen_paradas += '>';
                TR_origen_paradas += '<td>' + $(this).data("nombre_parada") + '</td>';
                TR_origen_paradas += '<td>' + nombre_ruta + '</td>';
                TR_origen_paradas += "</tr>";
                TRs_origen_paradas.push(TR_origen_paradas);
            });
        }
    });
    updateDataTableData("#destino_paradas .content table", TRs_destino_paradas);
    updateDataTableData("#origen_paradas .content table", TRs_origen_paradas);
};

$("#steps_content .content table").each(function() {
    createDataTable(this);
});

var createDateAndTimePickers = function() {
    $(".fecha").each(function() {
        $(this).datepicker({
            minDate: 0,
            maxDate: 0,
            beforeShowDay: function(date) {
                return false;
            }
        });
    });

    $(".hora").each(function() {
        $(this).timepicker({
            altField: '#ReservaHorario',
            onHourShow: function(hour) {
                return false;
            },
            onMinuteShow: function(hour, minute) {
                return false;
            }
        });
    });
};

var beforeSendReserva = function() {
    var $submitbtn = $("#planeomiviaje_menu form input[type=submit]");
    $submitbtn.attr({
        value: 'Reservando',
        disabled: 'disabled'
    });
};

var successSendReserva = function(data, textStatus) {
    if (data.errors != undefined) {
        var errors = 'ADVERTENCIA<br />';
        $.each(data.errors, function(property, value) {
            errors += '<p> - ' + value[0] + '</p>';
        });
        displayNotification(errors);
    }
    else {
        displayNotification(data.message);
        resetPlaneoMiViaje();
        if (data.reserva_details != undefined) {
            updateReservasTable(data.reserva_details.id_reserva, data.reserva_details.parada_origen, data.reserva_details.parada_destino, data.reserva_details.ruta, data.reserva_details.fecha, data.reserva_details.hora);
        }
        $("#planeomiviaje").click();
    }
};

var errorSendReserva = function(jqXHR, textStatus, errorThrown) {
    displayNotification("Ocurrio un error al hacer la reservación (" + errorThrown + ": " + textStatus + ")");
    $("#planeomiviaje").click();
};

var completeSendReserva = function() {
    var $submitbtn = $("#planeomiviaje_menu form input[type=submit]");
    $submitbtn.attr({
        value: 'Reservar'
    });
    $submitbtn.removeAttr('disabled');
};

var beforeSendReservaFromParada = function() {
    var $submitbtn = $("#mapapopups_menu .content .parada .submit input[type=button]");
    $submitbtn.attr({
        value: 'Reservando',
        disabled: 'disabled'
    });
};

var successSendReservaFromParada = function(data, textStatus) {
    if (data.errors != undefined) {
        var errors = 'ADVERTENCIA<br />';
        $.each(data.errors, function(property, value) {
            errors += '<p> - ' + value[0] + '</p>';
        });
        displayNotification(errors);
    }
    else {
        displayNotification(data.message);
        if (data.reserva_details != undefined) {
            updateReservasTable(data.reserva_details.id_reserva, data.reserva_details.parada_origen, data.reserva_details.parada_destino, data.reserva_details.ruta, data.reserva_details.fecha, data.reserva_details.hora);
        }
        $("#mapapopups_menu").hide();
    }
};

var errorSendReservaFromParada = function(jqXHR, textStatus, errorThrown) {
    displayNotification("Ocurrio un error al hacer la reservación (" + errorThrown + ": " + textStatus + ")");
};

var completeSendReservaFromParada = function() {
    var $submitbtn = $("#mapapopups_menu .content .parada .submit input[type=button]");
    $submitbtn.attr({
        value: 'Reservar'
    });
    $submitbtn.removeAttr('disabled');
};

var updateReservasTable = function(id_reserva, parada_origen, parada_destino, ruta, fecha, hora) {
    var formId = uniqid("post_", true);
    var reserva_tr = '<td>';
    reserva_tr += '<a href="/Reservas/editar/' + id_reserva + '" class="tooltip" tooltip-content="Editar"><span class="ui-icon ui-icon-white ui-icon-pencil"></span></a>';
    reserva_tr += ' | ';
    reserva_tr += '<form action="/Reservas/borrar/' + id_reserva + '" name="' + formId + '" id="' + formId + '" style="display:none;" method="post"><input type="hidden" name="_method" value="POST"></form>';
    reserva_tr += '<a href="#" class="tooltip" tooltip-content="Cancelar" onclick="document.' + formId + '.submit(); event.returnValue = false; return false;"><span class="ui-icon ui-icon-white ui-icon-cancel"></span></a>';
    reserva_tr += '</td>';
    reserva_tr += '<td>' + parada_origen + '</td>';
    reserva_tr += '<td>' + parada_destino + '</td>';
    reserva_tr += '<td>' + ruta + '</td>';
    reserva_tr += '<td>' + fecha + '</td>';
    reserva_tr += '<td>' + hora + '</td>';
    if ($("#reservas_programadas table tbody td.no_reservas").length != 0) {
        $("#reservas_programadas table tbody").empty();
    }
    $("#reservas_programadas table tbody").append('<tr>' + reserva_tr + '</tr>');
};

/*----------------------------------------------
 REFRESH BUTTON (MAP)
 ----------------------------------------------*/

$("#refresh").on("click tap", function(event) {
    if (popups_opened > 0) {
        displayNotification("Primero debe cerrar todos los menus de los buses y las paradas");
    }
    else {
        $(this).toggleClass('active');
        refreshUser = !refreshUser;
        if (refreshUser) {
            displayNotification("Ha activado la actualización del mapa");
        }
        else {
            displayNotification("Ha desactivado la actualización del mapa");
        }
    }
});

var refreshPress = function(refreshBool) {
    if (refreshBool) {
        $("#refresh").addClass('active');
        displayNotification("Se ha activado la actualización del mapa");
    }
    else {
        $("#refresh").removeClass('active');
        displayNotification("Se ha desactivado la actualización del mapa");
    }
};

/*----------------------------------------------
 FILTER BUTTON (MAP)
 ----------------------------------------------*/
function resetCheckboxFilter() {
    rutasFilter = [];
    $("#rutasFilter_menu input[type=checkbox]").each(function(index, el) {
        this.checked = false;
    });
    $("#rutasFilter_menu input[type=checkbox]").change();
}

var rutasFilter = [];
$("#rutasFilter_menu input[type=checkbox]").on('change', function(event) {
    event.preventDefault();
    if ($(this).is(':checked') && rutasFilter.indexOf($(this).data('id_ruta')) == -1) {
        rutasFilter.push($(this).data('id_ruta'));
    }
    else if (rutasFilter.indexOf($(this).data('id_ruta')) != -1) {
        rutasFilter.splice(rutasFilter.indexOf($(this).data('id_ruta')), 1);
    }
    if (rutasFilter.length != 0) {
        resetHaciaeiaDesdeeiaFilters();
        map.objects.remove(markersContainer.rutas);
        for (var i = markersContainer.rutas.objects.getLength() - 1; i >= 0; i--) {
            if (rutasFilter.indexOf(markersContainer.rutas.objects.get(i).get("id_ruta")) == -1) {
                markersContainer.rutas.objects.get(i).visibility = false;
            }
            else {
                markersContainer.rutas.objects.get(i).visibility = true;
            }
        }
        map.objects.add(markersContainer.rutas);

        var id_paradas_mostrar = [];
        $("#recorridos_activos .ruta_details").each(function() {
            if (rutasFilter.indexOf($(this).data("id_ruta")) != -1) {
                $(this).children(":not(.waypoint_details)").each(function(index, el) {
                    id_paradas_mostrar.push($(this).data("id_parada"));
                });
            }
        });

        map.objects.remove(markersContainer.paradas);
        for (var i = markersContainer.paradas.objects.getLength() - 1; i >= 0; i--) {
            if (id_paradas_mostrar.indexOf(markersContainer.paradas.objects.get(i).parada.id_parada) != -1) {
                markersContainer.paradas.objects.get(i).visibility = true;
                id_paradas_mostrar.splice(id_paradas_mostrar.indexOf(markersContainer.paradas.objects.get(i).parada.id_parada), 1);
            }
            else {
                markersContainer.paradas.objects.get(i).visibility = false;
            }
        }
        map.objects.add(markersContainer.paradas);
    }
    else {
        map.objects.remove(markersContainer.rutas);
        for (var i = markersContainer.rutas.objects.getLength() - 1; i >= 0; i--) {
            markersContainer.rutas.objects.get(i).visibility = true;
        }
        map.objects.add(markersContainer.rutas);

        map.objects.remove(markersContainer.paradas);
        for (var i = markersContainer.paradas.objects.getLength() - 1; i >= 0; i--) {
            markersContainer.paradas.objects.get(i).visibility = true;
        }
        map.objects.add(markersContainer.paradas);
    }
});

/****************************************************
 OTHER FUNCTIONS
 ****************************************************/

function sortObjects(objects, property, asc) {
    var length = objects.length;
    if (asc == true) {
        for (var i = 0; i < length; i++) {
            for (var j = length - 1; j > i; j--) {
                if (objects[j - 1][property] > objects[j][property]) {
                    var aux = objects[j - 1];
                    objects[j - 1] = objects[j];
                    objects[j] = aux;
                }
            }
        }
    }
    else {
        for (var i = 0; i < length; i++) {
            for (var j = length - 1; j > i; j--) {
                if (objects[j - 1][property] < objects[j][property]) {
                    var aux = objects[j - 1];
                    objects[j - 1] = objects[j];
                    objects[j] = aux;
                }
            }
        }
    }
    return objects;
}

function getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) {
    var R = 6371; // Radius of the earth in km
    var dLat = deg2rad(lat2 - lat1);  // deg2rad below
    var dLon = deg2rad(lon2 - lon1);
    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c; // Distance in km
    return d;
}

function deg2rad(deg) {
    return deg * (Math.PI / 180)
}

function decode_dias(dia) {
    switch (dia) {
        case "D":
            return 0;
            break;
        case "L":
            return 1;
            break;
        case "M":
            return 2;
            break;
        case "W":
            return 3;
            break;
        case "J":
            return 4;
            break;
        case "V":
            return 5;
            break;
        case "S":
            return 6;
            break;
    }
}

function translate_weekday(weekday) {
    switch (weekday) {
        case "Mon":
            return "Lunes";
            break;
        case "Tue":
            return "Martes";
            break;
        case "Wed":
            return "Mi&eacute;rcoles";
            break;
        case "Thu":
            return "Jueves";
            break;
        case "Fri":
            return "Viernes";
            break;
        case "Sat":
            return "S&aacute;bado";
            break;
        case "Sun":
            return "Domingo";
            break;
    }
}

function translate_month(month) {
    switch (month) {
        case "Jan":
            return "Ene";
            break;
        case "Feb":
            return "Feb";
            break;
        case "Mar":
            return "Mar";
            break;
        case "Apr":
            return "Abr";
            break;
        case "May":
            return "May";
            break;
        case "Jun":
            return "Jun";
            break;
        case "Jul":
            return "Jul";
            break;
        case "Aug":
            return "Ago";
            break;
        case "Sep":
            return "Sep";
            break;
        case "Oct":
            return "Oct";
            break;
        case "Nov":
            return "Nov";
            break;
        case "Dec":
            return "Dic";
            break;
    }
}

function uniqid(prefix, more_entropy) {
    if (typeof prefix === 'undefined') {
        prefix = "";
    }

    var retId;
    var formatSeed = function(seed, reqWidth) {
        seed = parseInt(seed, 10).toString(16); // to hex str
        if (reqWidth < seed.length) { // so long we split
            return seed.slice(seed.length - reqWidth);
        }
        if (reqWidth > seed.length) { // so short we pad
            return Array(1 + (reqWidth - seed.length)).join('0') + seed;
        }
        return seed;
    };

    // BEGIN REDUNDANT
    if (!this.php_js) {
        this.php_js = {};
    }
    // END REDUNDANT
    if (!this.php_js.uniqidSeed) { // init seed with big random int
        this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15);
    }
    this.php_js.uniqidSeed++;

    retId = prefix; // start with prefix, add current milliseconds hex string
    retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8);
    retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string
    if (more_entropy) {
        // for more entropy we add a float lower to 10
        retId += (Math.random() * 100000000).toFixed(0).toString();
    }

    return retId;
}